/**
  ******************************************************************************
  * @file    wizchipbsp.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "tskcfg.h"
#include "ethernet.h"

void wizchip_spi_init(void)
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  LL_EXTI_InitTypeDef EXTI_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI4);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOE);

  /* SPI4 GPIO Configuration
     PE2   ------> SPI4_SCK
     PE5   ------> SPI4_MISO
     PE6   ------> SPI4_MOSI */
  GPIO_InitStruct.Pin = ETH_SCK_Pin|ETH_MISO_Pin|ETH_MOSI_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOE, &GPIO_InitStruct);

  LL_GPIO_ResetOutputPin(GPIOE, ETH_CS_LL_Pin);
  LL_GPIO_ResetOutputPin(GPIOB, ETH_RST_LL_Pin);

  GPIO_InitStruct.Pin = ETH_CS_LL_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  LL_GPIO_Init(ETH_CS_GPIO_Port, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = ETH_RST_LL_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  LL_GPIO_Init(ETH_RST_GPIO_Port, &GPIO_InitStruct);
  
  /**/
  LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTB, LL_SYSCFG_EXTI_LINE5);

  EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_5;
  EXTI_InitStruct.LineCommand = ENABLE;
  EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
  EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
  LL_EXTI_Init(&EXTI_InitStruct);

  LL_GPIO_SetPinPull(ETH_INT_GPIO_Port, ETH_INT_Pin, LL_GPIO_PULL_UP);
  LL_GPIO_SetPinMode(ETH_INT_GPIO_Port, ETH_INT_Pin, LL_GPIO_MODE_INPUT);

  /* EXTI interrupt init*/
  NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),ETHERNET_EXIT_IRQ_PRIORITY, 0));
  NVIC_EnableIRQ(EXTI9_5_IRQn);
  
  /* SPI4 interrupt Init */
  NVIC_SetPriority(ETH_SPI_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),ETHERNET_SPI_IRQ_PRIORITY, 0));
  NVIC_DisableIRQ(ETH_SPI_IRQn);

  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 10;
  LL_SPI_Init(ETH_SPI, &SPI_InitStruct);

  LL_SPI_SetStandard(ETH_SPI, LL_SPI_PROTOCOL_MOTOROLA);

  LL_SPI_Enable(ETH_SPI);
}

void wizchip_ping_reset(void)
{
	eth_hard_reset(0);
	vTaskDelay(10);
  
	eth_hard_reset(1);
	vTaskDelay(100);
}

const static uint8_t eth_isr_msg = 1;

/**
  * @brief This function handles EXTI line[9:5] interrupts.
  */
void EXTI9_5_IRQHandler(void)
{
  if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5) != RESET)
  {
    LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
    
    if(ethernet_isr_qhd != NULL){
      xQueueSendFromISR(ethernet_isr_qhd, &eth_isr_msg, NULL);
    }
  }
}
